package com.naiterui.ehp.bs.emr.service.impl;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.collect.Lists;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.bo.emr.InquireCaseBO;
import com.naiterui.ehp.bp.bo.emr.PatientDiseaseBO;
import com.naiterui.ehp.bp.bo.patient.ConvertWxImageBO;
import com.naiterui.ehp.bp.bo.patient.PatientInquirerBO;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.beans.BeanUtil;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bs.emr.entity.mongo.PatientDisease;
import com.naiterui.ehp.bs.emr.entity.mongo.SessionInfo;
import com.naiterui.ehp.bs.emr.entity.mongo.UploadFile;
import com.naiterui.ehp.bs.emr.exception.ExceptionCodes;
import com.naiterui.ehp.bs.emr.feign.IPatientFeignClient;
import com.naiterui.ehp.bs.emr.repository.mongo.PatientDiseaseRepository;
import com.naiterui.ehp.bs.emr.service.IPatientDiseaseService;
import com.naiterui.ehp.bs.emr.utils.Constants;
import com.naiterui.ehp.bs.emr.utils.ImageUrlUtil;
import com.naiterui.ehp.bs.emr.utils.enums.DiseaseCycle;
import com.naiterui.ehp.bs.emr.utils.enums.DiseaseCycleEnum;
import com.naiterui.ehp.bs.emr.vo.UploadFileVO;
import com.naiterui.ehp.bs.emr.vo.patient.PatientDiseaseVO;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description 患者病情
 * @Author gongbaoqiang
 * @Date 2019/11/28 12:16 PM
 */
@Slf4j
@Service
public class PatientDiseaseServiceImpl implements IPatientDiseaseService {

    @Autowired
    private PatientDiseaseRepository diseaseRepository;

    @Autowired
    private IPatientFeignClient patientFeignClient;

    @Value("${ehp.domain.img}")
    private String imgDomain;


    @Override
    public List<DiseaseCycle> cycleList() throws BusinessException {

        return DiseaseCycleEnum.toList();
    }

    /**
     * 患者添加病情描述
     */
    @Override
    public String add(PatientDiseaseVO patientDiseaseParamVO) throws BusinessException {
        log.info("患者添加病情描述，图片信息为 {}", patientDiseaseParamVO.getOfflineDiagnosisImgs());
        //获取患者信息
        List<PatientInquirerBO> patientBOS = patientFeignClient.getPatientInquirer(Lists.newArrayList(patientDiseaseParamVO.getInquirerId()));
        if (CollectionUtils.isEmpty(patientBOS)) {
            log.error("就诊人信息不存在：inquirerId={}", patientDiseaseParamVO.getInquirerId());
            throw new BusinessException(ExceptionCodes.FAILED);
        }
        PatientInquirerBO patientBO = patientBOS.get(0);

        PatientDisease disease = new PatientDisease();
        BeanUtil.copyProperties(patientDiseaseParamVO, disease);
        disease.setContactName(patientBO.getContactName());
        disease.setContactPhone(patientBO.getContactPhone());
        disease.setPatientAge(patientBO.getAgeYear());
        disease.setPatientAgeUnit("岁");
        disease.setPatientAgeStr(patientBO.getAge());
        disease.setPatientGender(patientBO.getGender());
        disease.setPatientName(patientBO.getName());

        if (StringUtils.isBlank(patientDiseaseParamVO.getDrugs())) {
            disease.setDrugs("无");
        }

        if (StringUtils.isBlank(patientDiseaseParamVO.getPastHistory())) {
            disease.setPastHistory("无");
        }
        if (StringUtils.isBlank(patientDiseaseParamVO.getAllergy())) {
            disease.setAllergy("无");
        }

        //获取图片地址
        setDiseaseImgs(disease, patientDiseaseParamVO);
        if (!CollectionUtils.isEmpty(patientDiseaseParamVO.getOfflineERPdfs())) {
            //线下病例处方文件
            disease.setOfflineERPdfs(BeanUtil.copyList(patientDiseaseParamVO.getOfflineERPdfs(), Lists.newArrayList(), UploadFile.class));
        }

        // disease.setDiseaseCycle(DiseaseCycleEnum.get(patientDiseaseParamVO.getCycleCode()));
        disease.setCreateAt(new Date());
        disease.setCreateBy("SYSTEM");
        disease = diseaseRepository.save(disease);
        return disease.getId();
    }

    @Override
    public PatientDiseaseVO detail(String id) throws BusinessException {
        PatientDisease disease = diseaseRepository.get(id);
        PatientDiseaseVO vo = new PatientDiseaseVO();
        BeanUtil.copyProperties(disease, vo);
        Long inquirerId = disease.getInquirerId();
        if (null != inquirerId) {
            List<Long> inquirerIds = new ArrayList<>();
            inquirerIds.add(inquirerId);
            List<PatientInquirerBO> patientInquirerBOS = patientFeignClient.getPatientInquirer(inquirerIds);
            if (CollectionUtil.isNotEmpty(patientInquirerBOS)) {
                PatientInquirerBO patientInquirerBO = patientInquirerBOS.get(0);
                vo.setPastHistory(patientInquirerBO.getPastHistory());
                vo.setAllergy(patientInquirerBO.getAllergy());
            }
        }

        // vo.setDiseaseCycle(disease.getDiseaseCycle().getLabel());
        //设置图片地址
        /*if (CollectionUtil.isNotEmpty(vo.getOfflineERImgs())) {
            vo.setOfflineERImgs(vo.getOfflineERImgs().stream().map(ImageUrlUtil::getMedicalRecordImg
            ).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(vo.getDescriptionImgs())) {
            vo.setDescriptionImgs(vo.getDescriptionImgs().stream().map(ImageUrlUtil::getMedicalRecordImg
            ).collect(Collectors.toList()));
        }*/
//        if (CollectionUtil.isNotEmpty(vo.getOfflineDiagnosisImgs())) {
//            vo.setOfflineDiagnosisImgs(vo.getOfflineDiagnosisImgs().stream().map(ImageUrlUtil::getMedicalRecordImg
//            ).collect(Collectors.toList()));
//        }
        /*if (CollectionUtil.isNotEmpty(vo.getDrugsImgs())) {
            vo.setDrugsImgs(vo.getDrugsImgs().stream().map(ImageUrlUtil::getMedicalRecordImg
            ).collect(Collectors.toList()));
        }

        if (!CollectionUtils.isEmpty(disease.getOfflineERPdfs())) {
            //设置文件地址
            List<UploadFileVO> fileList = disease.getOfflineERPdfs().stream().map(s -> UploadFileVO.builder()
                .name(s.getName()).filepath(StringUtils.join(ImageUrlUtil.getImgDomain(), s.getFilepath())).build())
                .collect(Collectors.toList());
            vo.setOfflineERPdfs(fileList);
        }*/

        return vo;
    }

    @Override
    public List<String> uploadDiseaseImg(MultipartFile[] files) {
        String dayTime = DateUtil.getCurrentCustomizeFormatDate(DateUtil.DAY_TIME_FORMAT);
        List<String> imgUrlList = new ArrayList<>();

        if (null != files && files.length > 0) {
            Arrays.asList(files).forEach(img -> {
                try {
                    log.info("上传图片，图片信息 {}", img);
                    Long sn = RedisUtil.keyOps().incr(Constants.PATIENT_DISEASE_IMG_SN + dayTime);
                    String filePath = "/patient/" + dayTime + "/" + sn + ".jpg";
                    imgUrlList.add(imgDomain + "/emr" + filePath);
//                    imgUrlList.add(filePath);
                    log.info("上传图片，目标地址 {}", filePath);

                    byte[] mediaFile = img.getBytes();
                    String fileDir = ConfigUtil.getString("emr.file.path");
                    File file = new File(fileDir + filePath);
                    FileUtils.forceMkdirParent(file);
                    FileUtils.writeByteArrayToFile(file, mediaFile);
                } catch (IOException e) {
                    log.error("convertImage ERROR ; file={},error={}", img, e.getMessage());
                }
            });
        }

        return imgUrlList;
    }

    private void setDiseaseImgs(PatientDisease disease, PatientDiseaseVO patientDiseaseParamVO) throws BusinessException {
        List<ConvertWxImageBO> imgList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getOfflineERImgs())) {
            imgList.addAll(patientDiseaseParamVO.getOfflineERImgs().stream()
                .map(s -> ConvertWxImageBO.builder()
                    .mediaId(s)
                    .build()).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getDescriptionImgs())) {
            imgList.addAll(patientDiseaseParamVO.getDescriptionImgs().stream()
                .map(s -> ConvertWxImageBO.builder()
                    .mediaId(s)
                    .build()).collect(Collectors.toList()));
        }
        /*if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getOfflineDiagnosisImgs())) {
            imgList.addAll(patientDiseaseParamVO.getOfflineDiagnosisImgs().stream()
                .map(s -> ConvertWxImageBO.builder()
                    .mediaId(s)
                    .build()).collect(Collectors.toList()));
        }*/
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getDrugsImgs())) {
            imgList.addAll(patientDiseaseParamVO.getDrugsImgs().stream()
                .map(s -> ConvertWxImageBO.builder()
                    .mediaId(s)
                    .build()).collect(Collectors.toList()));
        }

        if (CollectionUtil.isEmpty(imgList)) {
            return;
        }
        disease.setOfflineDiagnosisImgs(patientDiseaseParamVO.getOfflineDiagnosisImgs());
        // disease.setOfflineDiagnosisImgs(this.uploadDiseaseImg(patientDiseaseParamVO.getOfflineDiagnosisImgFiles()));
        /*imgList = patientFeignClient.getDiseaseImgs(imgList);
        Map<String, String> map = imgList.stream().collect(
            Collectors.toMap(ConvertWxImageBO::getMediaId, ConvertWxImageBO::getImageUrl));

        //设置图片地址
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getOfflineERImgs())) {
            disease.setOfflineERImgs(patientDiseaseParamVO.getOfflineERImgs().stream().map(map::get
            ).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getDescriptionImgs())) {
            disease.setDescriptionImgs(patientDiseaseParamVO.getDescriptionImgs().stream().map(map::get
            ).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getOfflineDiagnosisImgs())) {
            disease.setOfflineDiagnosisImgs(patientDiseaseParamVO.getOfflineDiagnosisImgs().stream().map(map::get
            ).collect(Collectors.toList()));
        }
        if (CollectionUtil.isNotEmpty(patientDiseaseParamVO.getDrugsImgs())) {
            disease.setDrugsImgs(patientDiseaseParamVO.getDrugsImgs().stream().map(map::get
            ).collect(Collectors.toList()));
        }*/
    }

    @Override
    public List<String> getDiagnosis(String recordId) {
        PatientDisease disease = diseaseRepository.get(recordId);
        if (disease != null) {
            return Lists.newArrayList(disease.getOfflineDiagnosis());
        }
        return Lists.newArrayList();
    }

    @Override
    public PageVO<PatientDiseaseVO> list(Long patientId, PageParamVO pageParamVO) throws BusinessException {
        Page<PatientDisease> page = diseaseRepository.findByPatientId(patientId, pageParamVO.getPageable());
        List<PatientDiseaseVO> result = page.getContent().stream().map(s -> {
            PatientDiseaseVO vo = new PatientDiseaseVO();
            BeanUtils.copyProperties(s, vo);
            return vo;
        }).collect(Collectors.toList());
        return PageVO.newBuilder()
            .pageSize(page.getSize())
            .pageNo(page.getNumber())
            .totalCount((int) page.getTotalElements())
            .result(result)
            .build();
    }

    @Override
    public List<UploadFileVO> uploadPatientFile(MultipartFile[] files) throws BusinessException {
        List<UploadFileVO> filepathList = Lists.newArrayList();
        for (int i = 0; i < files.length; i++) {
            MultipartFile file = files[i];
            String originalFilename = file.getOriginalFilename();
            String filename = StringUtils.substring(originalFilename, 0, originalFilename.lastIndexOf("."));
            //文件后缀名
            String suffix = StringUtils.substring(originalFilename, originalFilename.lastIndexOf("."));
            String filepath = ImageUrlUtil.getEmrPatientFilePath() + UUID.randomUUID().toString() + suffix;
            try {
                FileUtils.writeByteArrayToFile(new File(ImageUrlUtil.getFileBasePath() + filepath), file.getBytes());
            } catch (IOException e) {
                log.error("文件上传失败：file={}", file.getOriginalFilename());
                throw new BusinessException(ExceptionCodes.FILE_UPLOAD_LOST);
            }
            filepathList.add(UploadFileVO.builder().name(filename).filepath(filepath).build());
        }

        return filepathList;
    }

    @Override
    public InquireCaseBO inquirerCase(String recordId) throws BusinessException {
        PatientDisease disease = diseaseRepository.get(recordId);
        if (disease == null) {
            throw new BusinessException(ExceptionCodes.RECORD_NOT_EXIST);
        }
        return InquireCaseBO.builder()
            .inquirerId(disease.getInquirerId())
            .diagnosis(Lists.newArrayList(disease.getOfflineDiagnosis()))
            .description(disease.getDescription())
            .build();
    }

    @Override
    public PatientDiseaseBO getPatientDisease(String diseaseId) {
        PatientDisease patientDisease = diseaseRepository.get(diseaseId);
        PatientDiseaseBO result = new PatientDiseaseBO();
        BeanUtil.copyProperties(patientDisease, result);
        result.setOfflineERImgs(patientDisease.getOfflineERImgs());
        List<String> offlineDiagnosisImgs = patientDisease.getOfflineDiagnosisImgs();
        if (CollectionUtil.isNotEmpty(offlineDiagnosisImgs)) {
            result.setOfflineDiagnosisImgs(offlineDiagnosisImgs.stream().map(e -> imgDomain + e).collect(Collectors.toList()));
        }
        result.setDescriptionImgs(patientDisease.getDescriptionImgs());
        result.setDrugsImgs(patientDisease.getDrugsImgs());
        return result;
    }

    @Override
    public PatientDiseaseBO getDisease(Long patientId) {
        PatientDisease patientDisease = diseaseRepository.findFirstByPatientIdOrderByCreateAtDesc(patientId);
        if (patientDisease == null) {
            return null;
        }
        PatientDiseaseBO result = new PatientDiseaseBO();
        BeanUtil.copyProperties(patientDisease, result);
        result.setOfflineERImgs(patientDisease.getOfflineERImgs());
        List<String> offlineDiagnosisImgs = patientDisease.getOfflineDiagnosisImgs();
        if (CollectionUtil.isNotEmpty(offlineDiagnosisImgs)) {
            result.setOfflineDiagnosisImgs(offlineDiagnosisImgs.stream().map(e -> "/emr" + e).collect(Collectors.toList()));
        }
        result.setDescriptionImgs(patientDisease.getDescriptionImgs());
        result.setDrugsImgs(patientDisease.getDrugsImgs());
        return result;
    }

    @Override
    public List<InquireCaseBO> inquirerDiseases(Set<String> diseaseIds) {
        List<PatientDisease> patientDiseases = diseaseRepository.findAllByIdIn(diseaseIds);
        if (CollectionUtils.isEmpty(patientDiseases)) {
            return new ArrayList<>();
        }
        return patientDiseases.stream()
            .map(disease -> InquireCaseBO.builder().id(disease.getId()).inquirerId(disease.getInquirerId())
                .diagnosis(Lists.newArrayList(disease.getOfflineDiagnosis())).description(disease.getDescription())
                .build())
            .collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sessionBind(String recordId, String sessionId) {
        PatientDisease disease = diseaseRepository.get(recordId);
        if (disease != null) {
            SessionInfo sessionInfo = disease.getSessionInfo();
            if (sessionInfo == null) {
                sessionInfo = new SessionInfo();
                sessionInfo.setForce(SessionInfo.FORCE_NO);
                sessionInfo.setSendTime(new Date());
            }
            sessionInfo.setSessionId(sessionId);
            disease.setSessionInfo(sessionInfo);
            this.diseaseRepository.update(disease);
        }
    }
}
